#include "stm32regbit.h"
#include "stm32regs.h"

void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset)
{
  SCB->VTOR = NVIC_VectTab | (Offset & (u32)0xFFFFFE00); //设置NVIC的向量表偏移寄存器,VTOR低9位保留,即[8:0]保留。
}

void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group)
{
  u32 temp, temp1;
  temp1 = (~NVIC_Group) & 0x07; //取后三位
  temp1 <<= 8;
  temp = SCB->AIRCR;  //读取先前的设置
  temp &= 0X0000F8FF; //清空先前分组
  temp |= 0X05FA0000; //写入钥匙
  temp |= temp1;
  SCB->AIRCR = temp; //设置分组
}

void MY_NVIC_Init(u8 NVIC_PreemptionPriority, u8 NVIC_SubPriority, u8 NVIC_Channel, u8 NVIC_Group)
{
  u32 temp;
  MY_NVIC_PriorityGroupConfig(NVIC_Group); //设置分组
  temp = NVIC_PreemptionPriority << (4 - NVIC_Group);
  temp |= NVIC_SubPriority & (0x0f >> NVIC_Group);
  temp &= 0xf;                                             //取低四位
  NVIC->ISER[NVIC_Channel / 32] |= 1 << NVIC_Channel % 32; //使能中断位(要清除的话,设置ICER对应位为1即可)
  NVIC->IP[NVIC_Channel] |= temp << 4;                     //设置响应优先级和抢断优先级
}

void GPIO_Set(GPIO_TypeDef *GPIOx, u32 BITx, u32 MODE, u32 OTYPE, u32 OSPEED, u32 PUPD)
{
  u32 pinpos = 0, pos = 0, curpin = 0;
  for (pinpos = 0; pinpos < 16; pinpos++)
  {
    pos = 1 << pinpos;   //一个个位检查
    curpin = BITx & pos; //检查引脚是否要设置
    if (curpin == pos)   //需要设置
    {
      GPIOx->MODER &= ~(3 << (pinpos * 2)); //先清除原来的设置
      GPIOx->MODER |= MODE << (pinpos * 2); //设置新的模式
      if ((MODE == 0X01) || (MODE == 0X02)) //如果是输出模式/复用功能模式
      {
        GPIOx->OSPEEDR &= ~(3 << (pinpos * 2));     //清除原来的设置
        GPIOx->OSPEEDR |= (OSPEED << (pinpos * 2)); //设置新的速度值
        GPIOx->OTYPER &= ~(1 << pinpos);            //清除原来的设置
        GPIOx->OTYPER |= OTYPE << pinpos;           //设置新的输出模式
      }
      GPIOx->PUPDR &= ~(3 << (pinpos * 2)); //先清除原来的设置
      GPIOx->PUPDR |= PUPD << (pinpos * 2); //设置新的上下拉
    }
  }
}

void gpio_config(GPIO_TypeDef *GPIOx, uint32_t pin)
{
  u32 tmpreg;
  uint32_t pin_pos = 0;
  pin_pos |= (1 << pin);
  //设置时钟
  /* Delay after an RCC peripheral clock enabling */
  if (GPIOx == GPIOA)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOASMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOASMEN_Msk);
  }
  else if (GPIOx == GPIOB)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOBSMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOBSMEN_Msk);
    ;
  }
  else if (GPIOx == GPIOC)
  {
    SET_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
    tmpreg = READ_BIT(RCC->AHB2ENR, RCC_AHB2SMENR_GPIOCSMEN_Msk);
    ;
  }
  (void)(tmpreg);
  WRITE_REG(GPIOx->BRR, pin_pos);

/* Initialize  pinpos on first pin set */
//pinpos = POSITION_VAL(GPIO_BSRR_BS5);
#if 1
  //设置模式
  /*MODIFY_REG(GPIOA->MODER, (GPIO_MODER_MODE0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U)),\
						 (GPIO_MODER_MODE0_0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U))); */
  GPIOx->MODER &= ~(3 << pin * 2U);
  GPIOx->MODER |= (1 << pin * 2U);
  //设置速度
  /*MODIFY_REG(GPIOA->OSPEEDR, (GPIO_OSPEEDR_OSPEED0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U)),\
						 (GPIO_OSPEEDR_OSPEED0_0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U)));*/
  GPIOx->OSPEEDR &= ~(3 << pin * 2U);
  GPIOx->OSPEEDR |= (0 << pin * 2U);
  //设置上下拉
  /*MODIFY_REG(GPIOA->PUPDR, (GPIO_PUPDR_PUPD0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U)),\
						 (0 << (POSITION_VAL(GPIO_BSRR_BS5) * 2U)));*/
  GPIOx->PUPDR &= ~(3 << pin * 2U);
  GPIOx->PUPDR |= (0 << pin * 2U);
  //设置输出模式  推挽
  MODIFY_REG(GPIOx->OTYPER, pin_pos, (pin_pos * 0));

  WRITE_REG(GPIOx->BSRR, pin_pos);
#endif
}

void GPIO_AF_Set(GPIO_TypeDef *GPIOx, u8 BITx, u8 AFx)
{
  GPIOx->AFR[BITx >> 3] &= ~(0X0F << ((BITx & 0X07) * 4));
  GPIOx->AFR[BITx >> 3] |= (u32)AFx << ((BITx & 0X07) * 4);
}

void GPIO_SET(GPIO_TypeDef *GPIOx, uint32_t pin, u8 status)
{
  if (status)
  {
    WRITE_REG(GPIOx->BSRR, 1 << pin);
  }

  else
  {
    WRITE_REG(GPIOx->BRR, 1 << pin);
  }
}